// 导入Swing GUI组件库
import javax.swing.*;
// 导入JavaScript引擎，用于数学表达式计算
import javax.script.ScriptEngine;
// 脚本引擎管理器
import javax.script.ScriptEngineManager;
// 脚本异常类
import javax.script.ScriptException;
// AWT图形用户界面库
import java.awt.*;
// AWT事件处理库
import java.awt.event.*;
// Java 日期时间API
import java.time.LocalDateTime;
// 日期时间格式化
import java.time.format.DateTimeFormatter;
// Java声音API
import javax.sound.sampled.*;
// 文件操作类
import java.io.File;
// IO异常类
import java.io.IOException;
// 图像IO类
import javax.imageio.ImageIO;
// 缓冲图像类
import java.awt.image.BufferedImage;
// 动态数组实现
import java.util.ArrayList;
// 列表接口
import java.util.List;
// 2D矩形几何形状
import java.awt.geom.Rectangle2D;

//高级计算器主类，继承自JFrame并实现ActionListener接口
//提供图形界面、计算功能、主题切换、音效和历史记录等功能
 public class EnhancedCalculator extends JFrame implements ActionListener {
    // 界面组件
    private JPanel north, center, south;  // 主界面分为北、中、南三个面板
    private JTextField field;             // 显示输入和结果的文本框
    private JTextArea historyArea;        // 显示计算历史的文本区域
    private JButton[] btns;               // 计算器按钮数组
    private JComboBox<String> themeSelector; // 主题选择下拉框

    // 音效相关变量
    private Clip buttonSound;           // 按钮点击音效
    private Clip backgroundMusic;       // 背景音乐
    private boolean playSound = true;   // 是否播放音效标志
    private boolean isMusicPlaying = false; // 背景音乐播放状态
    private float musicVolume = 1.0f;   // 背景音乐音量(0.0-1.0)

    // 主题设置枚举
    private enum Theme {
        // 定义四种主题，每种主题有名称、背景色和按键色
        LIGHT("浅色主题", new Color(245, 245, 245), new Color(240, 240, 240)),
        DARK("深色主题", new Color(60, 63, 65), new Color(50, 50, 50)),
        PINK("粉色主题", new Color(255, 228, 240), new Color(255, 200, 220)),
        BLUE("蓝色主题", new Color(225, 240, 255), new Color(200, 220, 255));
        
        final String name;            // 主题名称
        final Color backgroundColor;  // 背景颜色
        final Color buttonColor;      // 按键颜色
        
        // 主题构造方法
        Theme(String name, Color bgColor, Color btnColor) {
            this.name = name;//主题名称
            this.backgroundColor = bgColor;//主题背景色
            this.buttonColor = btnColor;//主题按键色
        }
    
        // 重写toString方法，返回主题名称
        @Override
        public String toString() {
             return name;
         }
    }
    // 当前主题设置，默认为粉色主题
    private Theme currentTheme = Theme.PINK;
    // 运算符按键颜色(带透明度)
    private Color operatorColor = new Color(255, 150, 150, 220);//前三数字代表RGB值，最后一个代表透明度
    // 特殊功能按钮颜色(带透明度)
    private Color specialColor = new Color(150, 255, 150, 220);

    // 背景图片
    private BufferedImage backgroundImage;
    
    // 计算历史记录列表
    private List<String> calculationHistory = new ArrayList<>();

    //计算器主构造方法
    public EnhancedCalculator() {
        setTitle("计算器");          // 设置窗口标题
        setSize(750, 850);            // 设置窗口大小(宽750,高850)
        setDefaultCloseOperation(EXIT_ON_CLOSE); // 设置关闭时退出程序
        setLocationRelativeTo(null);   // 窗口居中显示
        loadResources();              // 加载图片、音效等资源
        initComponent();              // 初始化界面组件
        
        // 添加窗口关闭监听器，用于释放资源
        addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                releaseResources();  // 窗口关闭时释放音效资源
            }
        });
        setVisible(true);             // 显示窗口
    }

    //加载资源方法(音效)
    private void loadResources() {
        try {
            // 加载按钮点击音效
            AudioInputStream audioStream = AudioSystem.getAudioInputStream(
                new File("button.wav"));
            buttonSound = AudioSystem.getClip();
            buttonSound.open(audioStream);
        } catch (Exception e) {
            System.out.println("按钮音效加载失败: " + e.getMessage());
            playSound = false; // 加载失败则禁用音效
        }
        try {
            // 加载背景音乐
            AudioInputStream musicStream = AudioSystem.getAudioInputStream(
                new File("music.WAV"));
            backgroundMusic = AudioSystem.getClip();
            backgroundMusic.open(musicStream);
            setMusicVolume(musicVolume); // 设置初始音量
        } catch (Exception e) {
            System.out.println("背景音乐加载失败: " + e.getMessage());
        }
    }
     //释放音效资源方法
    private void releaseResources() {
        if (buttonSound != null) {
            buttonSound.stop();  // 停止音效
            buttonSound.close(); // 关闭音效资源
        }
        if (backgroundMusic != null) {
            backgroundMusic.stop();  // 停止背景音乐
            backgroundMusic.close(); // 关闭音乐资源
        }
    }
    //设置背景音乐音量
    private void setMusicVolume(float volume) {
        if (backgroundMusic != null) {
            // 获取音量控制
            FloatControl gainControl = (FloatControl) backgroundMusic.getControl(
                FloatControl.Type.MASTER_GAIN);
            // 计算音量范围
            float range = gainControl.getMaximum() - gainControl.getMinimum();
            // 计算实际增益值
            float gain = (range * volume) + gainControl.getMinimum();
            gainControl.setValue(gain); // 设置音量
            musicVolume = volume; // 保存当前音量
        }
    }
    // 切换背景音乐播放状态
    private void toggleMusic() {
        if (backgroundMusic == null) return; // 无背景音乐则直接返回
        
        if (isMusicPlaying) {
            backgroundMusic.stop(); // 停止播放
        } else {
            backgroundMusic.loop(Clip.LOOP_CONTINUOUSLY); // 循环播放
            backgroundMusic.setFramePosition(0); // 从头开始
        }
        isMusicPlaying = !isMusicPlaying; // 切换状态
        // 显示状态提示
        String message = "背景音乐 " + (isMusicPlaying ? "已开启" : "已关闭");
        JOptionPane.showMessageDialog(this, message, "音乐控制", 
            JOptionPane.INFORMATION_MESSAGE);
    }
    // 初始化界面组件方法
    private void initComponent() {
        // 创建主容器并设置边框布局
        JPanel mainPanel = new JPanel(new BorderLayout(10, 10));
        mainPanel.setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 15)); // 设置边距
        mainPanel.setBackground(currentTheme.backgroundColor); // 设置背景色
        
        // 创建顶部面板(显示区域)
        north = new JPanel(new BorderLayout(10, 10));
        north.setOpaque(false); // 透明面板
        
        // 主题选择器
        themeSelector = new JComboBox<>();
        for (Theme theme : Theme.values()) {
            themeSelector.addItem(theme.name); // 添加所有主题选项
        }
        themeSelector.setSelectedItem(currentTheme.name); // 设置当前主题
        themeSelector.addActionListener(e -> changeTheme()); // 添加主题切换监听
        themeSelector.setFont(new Font("微软雅黑", Font.PLAIN, 14)); // 设置字体
        
        // 主题选择面板
        JPanel themePanel = new JPanel();
        themePanel.setOpaque(false); // 透明面板
        themePanel.add(new JLabel("主题:")); // 添加标签
        themePanel.add(themeSelector); // 添加下拉框
        north.add(themePanel, BorderLayout.EAST); // 添加到顶部面板右侧
        
        // 显示区域设置
        field = new JTextField();
        field.setPreferredSize(new Dimension(700, 100)); // 设置大小
        field.setFont(new Font("微软雅黑", Font.BOLD, 36)); // 设置字体
        field.setBackground(new Color(255, 255, 255, 220)); // 半透明白色背景
        // 设置复合边框(外边框+内边距)
        field.setBorder(BorderFactory.createCompoundBorder(
            BorderFactory.createLineBorder(new Color(150, 150, 150)), 
            BorderFactory.createEmptyBorder(10, 15, 10, 15)
        ));
        field.setEditable(false); // 禁止编辑
        field.setHorizontalAlignment(JTextField.RIGHT); // 文本右对齐
        north.add(field, BorderLayout.CENTER); // 添加到顶部面板中央
        
        // 中央面板 - 按钮区域
        center = new JPanel();
        center.setOpaque(false); // 透明面板
        center.setLayout(new GridLayout(5, 4, 15, 15)); // 5行4列网格布局
        center.setBorder(BorderFactory.createEmptyBorder(20, 0, 20, 0)); // 设置边距
        
        // 按钮标签数组
        String[] buttonLabels = {
            "7", "8", "9", "+",
            "4", "5", "6", "-", 
            "1", "2", "3", "×",
            "0", ".", "=", "÷",
            "C", "B", "T", "M"
        };
        
        // 创建按钮数组
        btns = new JButton[buttonLabels.length];
        for (int i = 0; i < btns.length; i++) {
            btns[i] = createButton(buttonLabels[i]); // 创建自定义按钮
            center.add(btns[i]); // 添加到中央面板
        }
        
        // 底部面板 - 历史记录
        south = new JPanel(new BorderLayout());
        south.setOpaque(false); // 透明面板
        
        // 历史记录文本区域
        historyArea = new JTextArea();
        historyArea.setEditable(false); // 禁止编辑
        historyArea.setFont(new Font("微软雅黑", Font.PLAIN, 16)); // 设置字体
        historyArea.setBackground(new Color(255, 255, 255, 250)); // 半透明白色背景
        
        // 历史记录滚动面板
        JScrollPane scrollPane = new JScrollPane(historyArea);
        // 设置带标题的边框
        scrollPane.setBorder(BorderFactory.createTitledBorder(
            BorderFactory.createLineBorder(new Color(150, 150, 150)), 
            "计算历史"));
        scrollPane.setOpaque(false); // 透明面板
        scrollPane.getViewport().setOpaque(false); // 透明视口
        
        south.add(scrollPane, BorderLayout.CENTER); // 添加到底部面板
        
        // 组装主界面
        mainPanel.add(north, BorderLayout.NORTH); // 顶部面板
        mainPanel.add(center, BorderLayout.CENTER); // 中央面板
        mainPanel.add(south, BorderLayout.SOUTH); // 底部面板
        
        setContentPane(mainPanel); // 设置主面板
    }

    //创建自定义样式按钮
    private JButton createButton(String text) {
        // 创建自定义按钮，重写paintComponent方法实现圆角效果
        JButton btn = new JButton(text) {
            @Override
            protected void paintComponent(Graphics g) {
                Graphics2D g2 = (Graphics2D) g.create(); // 创建图形副本
                // 开启抗锯齿
                g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 
                    RenderingHints.VALUE_ANTIALIAS_ON);
                
                // 根据按钮状态设置颜色
                if (getModel().isArmed()) { // 按钮被按下
                    g2.setColor(getBackground().darker());
                } else if (getModel().isRollover()) { // 鼠标悬停
                    g2.setColor(getBackground().brighter());
                } else { // 正常状态
                    g2.setColor(getBackground());
                }
                // 绘制圆角矩形背景
                g2.fillRoundRect(0, 0, getWidth(), getHeight(), 15, 15);
                
                // 绘制边框
                g2.setColor(new Color(100, 100, 100, 100));
                g2.drawRoundRect(0, 0, getWidth()-1, getHeight()-1, 15, 15);
                
                // 绘制文本
                g2.setColor(Color.BLACK); // 文本颜色
                FontMetrics fm = g2.getFontMetrics(); // 获取字体度量
                Rectangle2D r = fm.getStringBounds(text, g2); // 获取文本边界
                // 计算文本居中位置
                int x = (getWidth() - (int) r.getWidth()) / 2;
                int y = (getHeight() - (int) r.getHeight()) / 2 + fm.getAscent();
                g2.drawString(text, x, y); // 绘制文本
                
                g2.dispose(); // 释放图形资源
            }
        };
        
        // 设置按钮基本属性
        btn.setFont(new Font("微软雅黑", Font.BOLD, 28)); // 设置字体
        btn.addActionListener(this); // 添加点击监听
        btn.setFocusPainted(false); // 取消焦点绘制
        btn.setContentAreaFilled(false); // 取消默认填充
        btn.setBorder(BorderFactory.createEmptyBorder(5, 15, 5, 15)); // 设置内边距
        btn.setOpaque(false); // 透明背景
        
        // 根据按钮类型设置不同背景色
        if ("+-×÷".contains(text)) { // 运算符按钮
            btn.setBackground(operatorColor);
        } else if ("CB TM".contains(text)) { // 特殊功能按钮
            btn.setBackground(specialColor);
        } else { // 数字按钮
            btn.setBackground(currentTheme.buttonColor);
        }
        
        // 添加鼠标悬停效果
        btn.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseEntered(MouseEvent e) {
                btn.setCursor(new Cursor(Cursor.HAND_CURSOR)); // 手型光标
            }
            
            @Override
            public void mouseExited(MouseEvent e) {
                btn.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); // 默认光标
            }
        });
        
        return btn;
    }

    //切换主题方法
    private void changeTheme() {
        // 获取选中的主题名称
        String selected = (String)themeSelector.getSelectedItem();
        // 查找对应的主题枚举
        for (Theme theme : Theme.values()) {
            if (theme.name.equals(selected)) {
                currentTheme = theme; // 设置当前主题
                break;
            }
        }
        
        // 更新主面板背景色
        getContentPane().setBackground(currentTheme.backgroundColor);
        
        // 更新所有按钮颜色
        for (JButton btn : btns) {
            String text = btn.getText();
            if ("+-×÷".contains(text)) { // 运算符按钮
                btn.setBackground(operatorColor);
            } else if ("CB TM".contains(text)) { // 特殊功能按钮
                btn.setBackground(specialColor);
            } else { // 数字按钮
                btn.setBackground(currentTheme.buttonColor);
            }
            btn.repaint(); // 重绘按钮
        }
    }

    /**
     * 按钮点击事件处理方法
     */
    @Override
    public void actionPerformed(ActionEvent e) {
        String command = e.getActionCommand(); // 获取按钮命令
        String currentText = field.getText(); // 获取当前文本
        
        playButtonSound(); // 播放按钮音效
        
        // 根据按钮类型执行不同操作
        switch (command) {
            case "C": // 清除
                field.setText("");
                break;
            case "B": // 退格
                if (!currentText.isEmpty()) {
                    field.setText(currentText.substring(0, currentText.length()-1));
                }
                break;
            case "T": // 显示当前时间
                field.setText(LocalDateTime.now().format(
                    DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
                break;
            case "M": // 音乐控制
                toggleMusic();
                break;
            case "=": // 计算结果
                calculateResult();
                break;
            case ".": // 小数点
                handleDecimalPoint(currentText);
                break;
            case "+": case "-": case "×": case "÷": // 运算符
                handleOperator(currentText, command);
                break;
            default: // 数字
                field.setText(currentText + command);
        }
    }

    //播放按钮音效方法
    private void playButtonSound() {
        if (playSound && buttonSound != null) {
            try {
                buttonSound.setFramePosition(0); // 重置到开头
                buttonSound.start(); // 开始播放
            } catch (Exception e) {
                System.out.println("播放按钮音效失败: " + e.getMessage());
            }
        }
    }
    //处理小数点输入
    private void handleDecimalPoint(String currentText) {
        if (currentText.isEmpty()) {
            field.setText("0."); // 空文本时添加"0."
        } else if (currentText.endsWith(".") || currentText.matches(".*[+\\-×÷]$")) {
            return; // 已有点或运算符结尾时不处理
        } else {
            // 分割表达式，检查最后一部分是否已包含小数点
            String[] parts = currentText.split("[+\\-×÷]");
            if (!parts[parts.length-1].contains(".")) {
                field.setText(currentText + "."); // 添加小数点
            }
        }
    }
    //处理运算符输入
    private void handleOperator(String currentText, String operator) {
        if (currentText.isEmpty()) {
            return; // 空文本不处理
        } else if (currentText.matches(".*[+\\-×÷]$")) {
            // 替换最后一个运算符
            field.setText(currentText.substring(0, currentText.length()-1) + operator);
        } else {
            field.setText(currentText + operator); // 添加运算符
        }
    }
    //计算结果方法
    private void calculateResult() {
        try {
            String expression = field.getText().trim(); // 获取表达式
            if (expression.isEmpty()) return; // 空表达式不处理
            
            // 替换乘除号为JavaScript识别的符号
            expression = expression.replace("×", "*").replace("÷", "/");
            
            // 验证表达式有效性
            if (!isValidExpression(expression)) {
                showErrorDialog("无效的表达式!");
                return;
            }
    
            // 使用JavaScript引擎计算
            ScriptEngineManager manager = new ScriptEngineManager();
            ScriptEngine engine = manager.getEngineByName("js");
            Object result = engine.eval(expression); // 执行计算
            
            // 添加到历史记录
            String historyEntry = expression + " = " + result;
            calculationHistory.add(historyEntry);
            updateHistoryDisplay(); // 更新历史显示
            
            field.setText(result.toString()); // 显示结果
            
            animateResult(); // 添加结果动画效果
        } catch (ScriptException ex) {
            showErrorDialog("计算错误: " + ex.getMessage()); // 显示错误
        }
    }

    // 结果动画效果
    private void animateResult() {
        Timer timer = new Timer(50, null); // 创建定时器(50ms间隔)
        final int[] counter = {0}; // 动画计数器
        final Color originalColor = field.getBackground(); // 保存原始背景色
        
        // 定时器事件处理
        timer.addActionListener(e -> {
            if (counter[0] < 10) { // 执行10次动画
                float ratio = counter[0] / 10.0f; // 计算动画进度
                // 计算渐变颜色(从原色到浅绿色)
                int r = (int)(originalColor.getRed() * (1 - ratio) + 200 * ratio);
                int g = (int)(originalColor.getGreen() * (1 - ratio) + 255 * ratio);
                int b = (int)(originalColor.getBlue() * (1 - ratio) + 200 * ratio);
                field.setBackground(new Color(r, g, b, originalColor.getAlpha()));
                counter[0]++; // 增加计数器
            } else {
                field.setBackground(originalColor); // 恢复原色
                ((Timer)e.getSource()).stop(); // 停止定时器
            }
        });
        timer.start(); // 启动定时器
    }

    //显示错误对话框
     
    private void showErrorDialog(String message) {
        JOptionPane.showMessageDialog(this, message, "错误", 
            JOptionPane.ERROR_MESSAGE);
    }

    //更新历史记录显示
    private void updateHistoryDisplay() {
        StringBuilder sb = new StringBuilder();
        // 只显示最近5条记录
        int start = Math.max(0, calculationHistory.size() - 5);
        for (int i = start; i < calculationHistory.size(); i++) {
            sb.append(calculationHistory.get(i)).append("\n");
        }
        historyArea.setText(sb.toString()); // 设置历史文本
        // 滚动到最底部
        historyArea.setCaretPosition(historyArea.getDocument().getLength());
    }
    private boolean isValidExpression(String expr) {
        if (expr.isEmpty()) return false; // 空表达式无效
        // 不能以运算符开头或结尾
        if (expr.matches("^[+\\-*/].*") || expr.matches(".*[+\\-*/]$")) {
            return false;
        }
        // 不能有连续的运算符
        if (expr.matches(".*[+\\-*/]{2,}.*")) {
            return false;
        }
        // 只能包含数字、运算符、空格和点
        if (!expr.matches("^[0-9+\\-*/. ]+$")) {
            return false;
        }
        return true;
    }

    // 程序入口
    public static void main(String[] args) {
        // 使用SwingUtilities.invokeLater确保GUI线程安全
        SwingUtilities.invokeLater(() -> {
            try {
                // 设置系统外观
                UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
            } catch (Exception e) {
                e.printStackTrace();
            }
            new EnhancedCalculator(); // 创建计算器实例
        });
    }
}